//
// Created by Zhang on 2022/5/5.
//
#include <cmath>
#include <string>
#include <iostream>
#include <cmath>

//chapter4 q1
class CStudent {
    std::string name, home;
    long id;
    int age, score;
public:
    CStudent(std::string n, std::string h, long i, int a, int s) : name(n), home(h), id(i), age(a), score(s) {};

    CStudent(const CStudent &a) {
        name = a.name;
        home = a.home;
        id = a.id;
        age = a.age;
        score = a.score;
    }

    void Display();

    int operator+(const CStudent &b) const {
        return score + b.score;
    }
};

void CStudent::Display() {
    std::cout << "name:" << name << ",home:" << home << ",id:" << id << ",age:" << age << ",score:" << score
              << std::endl;

}

//chapter4 q2
class Triangle {
    float a, b, c;
public:
    float area() const;

    float operator+(Triangle &) const;

    Triangle(float a, float b, float c) : a(a), b(b), c(c) {};
};

float Triangle::area() const {
    float p = (a + b + c) / 2;
    float s = std::sqrt(p * (p - a) * (p - b) * (p - c));
    return s;
}

float Triangle::operator+(Triangle &d) const {
    return area() + d.area();
}

//extra q2

class Complex {
    float real, image;
public:
    void show() const {
        std::cout << real << ((image > 0) ? "+" : "-") << std::abs(image) << "i" << std::endl;
    }

    Complex(float a, float b) : image(b), real(a) {};

    Complex &operator=(const Complex &a);

    Complex operator+(const Complex &b) const;

    Complex operator-(const Complex &b) const;

    Complex operator+=(const Complex &b);

    Complex operator-=(const Complex &b);

    Complex operator*(const Complex &b) const;

    Complex operator/(const float &b) const;

    Complex operator/(const Complex &b) const;


};

Complex &Complex::operator=(const Complex &a) {
    this->image = a.image;
    this->real = a.real;
    return *this;
}

Complex Complex::operator+(const Complex &b) const {
    return Complex(real + b.real, image + b.image);
}

Complex Complex::operator-(const Complex &b) const {
    return Complex(real - b.real, image - b.image);
}

Complex Complex::operator+=(const Complex &b) {
    *this = *this + b;
    return *this;
}

Complex Complex::operator-=(const Complex &b) {
    *this = *this - b;
    return *this;
}

Complex Complex::operator*(const Complex &b) const {
    return Complex(real * b.real - image * b.image, real * b.image + image * b.real);
}

//
Complex Complex::operator/(const Complex &b) const {
    Complex b_r(b.real, -b.image);
    float abs = (b * b_r).real;
    return *this * *this / abs;
}

Complex Complex::operator/(const float &b) const {
    return Complex(real / b, image / b);
}

//extra q3
class CPoint {
    int x, y;
public:
    CPoint(int a, int b) : x(a), y(b) {};

    friend CPoint operator++(CPoint &);

    friend CPoint operator++(CPoint &, int);

    void show() {
        std::cout << "(" << x << "," << y << ")" << std::endl;
    }

};

CPoint operator++(CPoint &a) {
    a.y++;
//    a.x++;
    return a;
}

CPoint operator++(CPoint &a, int) {
    a.x++;
    return a;
}


int main() {
    //chapter4 q1
    CStudent a("Sandy", "USA", 123050, 20, 99);
    a.Display();
    CStudent b(a);
    b.Display();
    std::cout << a + b << std::endl;

    //chapter4 q2
    Triangle c(3, 4, 5), d(5, 12, 13);
    std::cout << c.area() << " " << d.area() << " " << c + d << std::endl;

    //extra q2
    Complex q2a(1, 2), q2b(2, 3);
    Complex q2c = q2a * q2b;
    (q2a + q2b).show();
    q2c.show();
    (q2a - q2c).show();
    (q2a * q2b).show();
    (q2a / q2b).show();
    (q2a / 3).show();
    q2a += q2b;
    q2a.show();
    q2a -= q2b;
    q2a.show();

    //extra q3
    CPoint q3a(1, 1);
    q3a.show();
    q3a++;
    q3a.show();
    ++q3a;
    q3a.show();


    return 0;
}